package com.yunqian.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yunqian.constant.SwiftpassConfig;
import com.yunqian.redot.constant.OrderStatus;
import com.yunqian.redot.domain.CoursesOrder;
import com.yunqian.redot.domain.SwiftpassPay;
import com.yunqian.redot.domain.Ticket;
import com.yunqian.redot.domain.TicketOrder;
import com.yunqian.redot.service.CoursesOrderService;
import com.yunqian.redot.service.SwiftpassPayService;
import com.yunqian.redot.service.TicketOrderService;
import com.yunqian.redot.service.TicketService;
import com.yunqian.util.ZPTUtil;
import com.yunqian.util.swiftpass.SignUtils;
import com.yunqian.util.swiftpass.SwiftpassUtil;
import com.yunqian.util.swiftpass.XmlUtils;
import com.yunqian.util.validate.Validator;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.json.JsonbTester;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author czy
 * @describe
 * @date 2018/10/17
 */
@Log4j2
@RestController
@RequestMapping("/api/swiftpass")
public class SwiftpassController {

    @Autowired
    private CoursesOrderService coursesOrderService;
    @Autowired
    private TicketOrderService ticketOrderService;
    @Autowired
    private SwiftpassPayService swiftpassPayService;
    @Autowired
    private TicketService ticketService;

    /**
     * 预下单测试接口
     * @param params
     * @return
     */
    @PostMapping("/pay")
    public Map<String, String> pay(@RequestBody Map<String, Object> params) {
        Map<String, String> map = SwiftpassUtil.prepayment((String) params.get("orderId"), "body", null, "", "0.01", "127.0.0.1");
        return map;
    }

    /**
     * 支付回调
     */
    @RequestMapping("/notify")
    public void callBack(HttpServletRequest request, HttpServletResponse response) {
        log.warn("call back execute...");
        // 回调信息
        Map<String, String> map = XmlUtils.parseRequst(request);
        // 判断交易状态
        if("0".equals(map.get("status")) && "0".equals(map.get("result_code"))){
            // 商户订单号
            String outTradeNo = map.get("out_trade_no");
            String attach = map.get("attach");
            if("course_order".equals(attach)){
                // 课程订单流程
                coursesHandle(outTradeNo, map, response);
            }else if("ticket_order".equals(attach)){
                // 购票订单流程
                ticketHandle(outTradeNo, map, response);
            }else {
                return;
            }
            // 保存回调消息
            swiftpassPayService.update(outTradeNo, map.get("pay_result"),map.get("pay_info"),
                    map.get("transaction_id"),map.get("out_transaction_id"),map.get("total_fee"),
                    map.get("bank_type"),map.get("time_end"));
            out("success",response);
        }else {
            out("error",response);
        }
    }

    private void coursesHandle(String outTradeNo, Map<String,String> map, HttpServletResponse response){
        // 1.首先判断订单状态 已通知过的订单（支付成功/失败）直接返回 "success"
        CoursesOrder order = coursesOrderService.findByOrderNo(outTradeNo);
        if(!OrderStatus.NEW.getCode().equals(order.getStatus())){
            out("success",response);
            return;
        }
        // 2.验证签名
        if(!SignUtils.checkParam(map, SwiftpassConfig.KEY)){
            log.warn("签名校验失败");
            out("error",response);
            return;
        }
        // 3.对比订单金额
        String totalFee = SwiftpassUtil.getMoney(order.getPrice().toString());
        if(!totalFee.equals(map.get("total_fee"))){
            log.warn("订单金额不匹配");
            out("error",response);
            return;
        }
        // 处理订单逻辑
        order.setPayTime(new Date());
        order.setStatus(OrderStatus.SUCCESS.getCode());
        coursesOrderService.update(order);
    }

    private void ticketHandle(String outTradeNo, Map<String,String> map, HttpServletResponse response){
        // 1.首先判断订单状态 已通知过的订单（支付成功/失败）直接返回 "success"
        TicketOrder order = ticketOrderService.findByOrderNo(outTradeNo);
        if(!OrderStatus.NEW.getCode().equals(order.getStatus())){
            out("success",response);
            return;
        }
        // 2.验证签名
        if(!SignUtils.checkParam(map, SwiftpassConfig.KEY)){
            log.warn("签名校验失败");
            out("error",response);
            return;
        }
        // 3.对比订单金额
        String totalFee = SwiftpassUtil.getMoney(order.getPrice().multiply(new BigDecimal(order.getQuantity())).toString());
        if(!totalFee.equals(map.get("total_fee"))){
            log.warn("订单金额不匹配");
            out("error",response);
            return;
        }
        // 众票通下单
        zptOrder(order);
        order.setPayTime(new Date());
        order.setStatus(OrderStatus.SUCCESS.getCode());
        ticketOrderService.update(order);
    }

    /**
     * 支付成功 -众票通下单
     * @param order
     */
    private void zptOrder(TicketOrder order){
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String ticketStr = order.getRelateTicketArr();
            Ticket ticket = ticketService.getFirstByRelateTicketArr(ticketStr);
            String result = ZPTUtil.createOrder(order.getOrderNo(), ticket.getTicketTypeCode(), dateFormat.format(new Date()), order.getQuantity().toString(), ticket.getPrice().toString() );
            JSONObject obj = JSONObject.parseObject(result);
            String code = obj.getJSONObject("body").getString("code");
            String codeURL = obj.getJSONObject("body").getString("codeURL");
            // 处理订单逻辑
            order.setTicketCode(code);
            order.setTicketQrCode(codeURL);
            ticketOrderService.update(order);
        } catch (Exception e) {
            log.warn("众票通下单失败，订单号：" + order.getOrderNo());
        }
    }

    /**
     * 应答
     *
     * @param return_code
     * @param response
     * @throws IOException
     */
    private void out(String return_code, HttpServletResponse response) {
        // 通过流的方式将结果返回给微信
        BufferedOutputStream out = null;
        try {
            out = new BufferedOutputStream(response.getOutputStream());
            out.write(return_code.getBytes());
            out.flush();
        } catch (IOException e) {
            log.warn("The reply message XML writes to the IO stream exception", e);
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
